#include <iostream>
#include <SDL_image.h>
#include "Game.h"
#include "Player.h"
#include "Enemy.h"
#include "InputHandler.h"
#include "MenuState.h"
#include "MainMenuState.h"
#include "PlayState.h"
#include "GameObjectFactory.h"
#include "MenuButtonCreator.h"
#include "EnemyCreator.h"

Game * Game::s_pInstance = nullptr;

bool Game::init(const char *title,
               int xpos, int ypos,
               int width, int height,
               int flags){
    m_gameWidth = width;
    m_gameHeight = height;
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
        std::cout << "Init sdl fault" << std::endl;
        return false;
    }

    std::cout << "SDL init success" <<std::endl;
    //init window
    m_pWindow = SDL_CreateWindow(title,
                                xpos, ypos,
                                width, height,
                                flags);
    if (m_pWindow == nullptr){
        std::cout << "window init fault" <<std::endl;
        return false;
    }

    std::cout << "window creation success" <<std::endl;
    m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
    if (m_pRenderer == nullptr){
        std::cout << "render init fail" << std::endl;
        return false;
    }
    std::cout << "renderer creation success" << std::endl;
#if 0
    SDL_Surface * pTempSurface = SDL_LoadBMP("assets/rider.bmp");
#else
//    SDL_Surface * pTempSurface = SDL_LoadBMP("assets/animate.bmp");
    //SDL_Surface * pTempSurface = IMG_Load("assets/animate.png");
#endif
   // m_pTexture = SDL_CreateTextureFromSurface(m_pRenderer, pTempSurface);
   // SDL_FreeSurface(pTempSurface);
   //m_textureManager.load("assets/animate.png", "animate", m_pRenderer);
    TextureManager::Instance()->load("assets/animate.png", "animate", m_pRenderer);
    //SDL_QueryTexture(m_pTexture, NULL, NULL, 
    //        &m_sourceRectangle.w, &m_sourceRectangle.h);
#if 0
    m_sourceRectangle.w = 50;
    m_sourceRectangle.h = 50;
    m_sourceRectangle.x = 50;
    m_sourceRectangle.y = 50;

    m_destinationRectangle.x = 100;
    m_destinationRectangle.y = 100;
#endif
    m_sourceRectangle.w = 128;
    m_sourceRectangle.h = 82;
    m_sourceRectangle.x = 0;
    m_sourceRectangle.y = 0;


  //  m_destinationRectangle.w = 50;
  //  m_destinationRectangle.h = 50;

    //set distinction x,y,width,height
    //m_destinationRectangle.x = m_sourceRectangle.x = 0;
    //m_destinationRectangle.y = m_sourceRectangle.y = 0;
    
    m_destinationRectangle.w = m_sourceRectangle.w;
    m_destinationRectangle.h = m_sourceRectangle.h;
#if 1    
    SDL_RenderCopy(m_pRenderer, m_pTexture, &m_sourceRectangle, 
                   &m_destinationRectangle);
#else
    SDL_RenderCopy(m_pRenderer, m_pTexture, 0, 
                   0);

#endif


    SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 255);
        
    // setting is_running to true
    m_bRunning = true;
#if 0
    m_gameObjects.push_back(new Player(new LoaderParams(100, 100, 
                                                        128, 82, 
                                                        "animate")));
    m_gameObjects.push_back(new Enemy(new LoaderParams(300, 300, 
                                                        128, 82, 
                                                        "animate")));
#endif

    TheInputHandler::Instance()->initialiseJoysticks();
#if 0
    m_go = new GameObject();
    // create player
    m_player = new Player();
    m_enemy = new Enemy();

    m_go->load(100, 100, 128, 82, "animate");
    m_player->load(300, 300, 128, 82, "animate");
    m_enemy->load(0, 0, 128, 82, "animate");
#endif

    // create enemy
   // m_enemy1 = new Enemy(); 
   // m_enemy2 = new Enemy(); 
   // m_enemy3 = new Enemy(); 

#if 0
    m_gameObjects.push_back(m_go);
    m_gameObjects.push_back(m_player);
    m_gameObjects.push_back(m_enemy);
#endif    
    //m_gameObjects.push_back(m_enemy1);
    //m_gameObjects.push_back(m_enemy2);
    //m_gameObjects.push_back(m_enemy3);

    m_pMenuObj1 = new MenuObject();
    m_pMenuObj2 = new MenuObject();
#if 0
    m_player = new Player(new LoaderParams(100, 100, 
                                           128, 82, 
                                          "animate"));
    m_enemy = new Enemy(new LoaderParams(300, 300, 
                                         128, 82, 
                                         "animate"));
#endif
#if 1
    m_currentGameState = MENU;
    TheGameObjectFactory::Instance()->registerType(
            "MenuButton",
            new MenuButtonCreator()
            );    
    TheGameObjectFactory::Instance()->registerType(
            "Player",
            new PlayerCreator()
            );    
    TheGameObjectFactory::Instance()->registerType(
            "Enemy",
            new EnemyCreator()
            );

    m_pGameStateMachine = new GameStateMachine();
    m_pGameStateMachine->changeState(new MainMenuState());
#endif

    // load tileset layer

    
    return true;
}

void Game::render(){
    SDL_RenderClear(m_pRenderer);
//    SDL_RenderCopy(m_pRenderer, m_pTexture, &m_sourceRectangle, 
//                   &m_destinationRectangle);
//    SDL_RenderCopyEx(m_pRenderer, m_pTexture, &m_sourceRectangle, 
//                   &m_destinationRectangle, 0, 0, SDL_FLIP_HORIZONTAL);
#if 0
    m_textureManager.draw("animate", 0, 0, 128, 82, m_pRenderer);
    m_textureManager.drawFrame("animate", 100, 100, 128, 82, 1, m_currentFrame, m_pRenderer);
#endif
#if 0     
    for (std::vector<GameObject*>::size_type i = 0; i != m_gameObjects.size(); 
            i++){
        m_gameObjects[i]->draw();

    }
#endif    

    m_pGameStateMachine->render();

    //get source rectangle width and height
    SDL_RenderPresent(m_pRenderer);
}

void Game::update(){
   // m_sourceRectangle.x = 128 * int((SDL_GetTicks()/100) % 6);
    /*
    for(std::vector<GameObject*>::size_type i = 0; i != m_gameObjects.size();
            i++){
        m_gameObjects[i]->update();
    }
    */
    switch (m_currentGameState){
        case MENU:
            m_pMenuObj1->update();
            m_pMenuObj2->update();
            break;
        case PLAY:
            m_player->update();
            m_enemy->update();
            break;
        case GAMEOVER:
            //todo::
            break;
    }

    m_pGameStateMachine->update();
}

void Game::clean(){
    std::cout << "cleaning game" << std::endl;
    TheInputHandler::Instance()->clean();
    SDL_DestroyWindow(m_pWindow);
    SDL_DestroyRenderer(m_pRenderer);
    SDL_Quit();
}

void Game::setCurrentLevel(int currentLevel){
    m_currentLevel = currentLevel;
    m_pGameStateMachine->changeState(new BetweenLevelState());
    m_bLevelComplete = false;
}

void Game::handleEvents(){
    TheInputHandler::Instance()->update();

    if (TheInputHandler::Instance()->isKeyDown(SDL_SCANCODE_RETURN)){
        m_pGameStateMachine->changeState(new PlayState());
    }
}

















